//
//  TestTrack.m
//  Racing
//
//  Created by vy phan on 4/14/11.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import "TestTrack.h"
#define TEST_CG_DRAW
//#define USE_CGDRAWING
@implementation TestTrack

//1. Created a blank bitmap
CGContextRef CreateDrawingBitmapContext(int pixelsWide, int pixelsHigh) {
	CGContextRef context = NULL;
	CGColorSpaceRef colorSpace;
	void * bitmapData;
	int bitmapByteCount;
	int bitmapBytesPerRow;
	bitmapBytesPerRow = (pixelsWide * 4);
	bitmapByteCount = (bitmapBytesPerRow * pixelsHigh);
	colorSpace = CGColorSpaceCreateDeviceRGB();
	bitmapData = malloc( bitmapByteCount );
	if (bitmapData == NULL)
	{
		NSLog( @"Memory not allocated!");
		return NULL;
	}
	context = CGBitmapContextCreate (bitmapData,
									 pixelsWide,
									 pixelsHigh,
									 8, // bits per component
									 bitmapBytesPerRow,
									 colorSpace,
									 kCGImageAlphaPremultipliedFirst);
	if (context== NULL)
	{
		free (bitmapData);
		NSLog( @"Context not created!");
		return NULL;
	}
	CGColorSpaceRelease( colorSpace );
	return context;
}
static inline float clamp(float a, float min, float max) {
	if (a < min) return min;
	if (a > max) return max;
	
	return a;
}

-(void) paintTrack {

		
}
-(id)init {
	CGSize s = [[CCDirector sharedDirector] winSize];
	self = [super init];
	if (self != nil) {
		track = [[Track alloc]init];
		NSString *filePath = [[NSBundle mainBundle] pathForResource:@"donington" ofType:@"track"];
		if (filePath) {
			NSLog(filePath);
			[track load:filePath];
		}
		else {
			printf(">>>>>>>>>>>>>>>>>>>> file not exits.\n");
		}
	}
	self.isTouchEnabled = TRUE;
	//self.isMouseEnabled
	//[self drawContextLine];
	
	int sectionsCount = [track->sections count];
	Rectangle* firstBound = [((Section*)[track->sections objectAtIndex:0]) getBounds];
	maxPosX = [firstBound x];
	maxPosY = [firstBound y];
	for (int i = 1; i < sectionsCount; i++) {
		Section *section = (Section*)[track->sections objectAtIndex:i];
		Rectangle *bounds = [section getBounds];
		if ([bounds x] > maxPosX) {
			maxPosX = [bounds x];
		}
		if ([bounds y] > maxPosY) {
			maxPosY = [bounds y];
		}
	}
	
	vehicles = [[NSMutableArray alloc]initWithCapacity:1];
	for (int i = 0; i < 1; i++) {
		Vehicle *vh = [[Vehicle alloc] initWithId:(char)i X:224 + i*10 Y:128];
		[vehicles addObject:vh];
	}
	vehicle = (Vehicle*)[vehicles objectAtIndex:0];
	race = [[Race alloc]initWithLocalVehicle:vehicle Track:track Vehicles:vehicles];
	self.isAccelerometerEnabled = YES;
	[self reset];
	
	DrawingBitmap = CreateDrawingBitmapContext(maxPosX + SECTION_WIDTH, maxPosY + SECTION_HEIGHT);
	drawing = [[CGDrawing alloc] init];
	[self schedule:@selector(gameUpdate:) interval:0.05f];
	//[self DrawFilledPath];
	return self;
}
-(void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
    CGSize winsize = [[CCDirector sharedDirector] winSize];
	
	// grab the player sprite from that layer using it's tag
    CCSprite *playerSprite = (CCSprite *)[self getChildByTag:1];
	
	
	float destX, destY;
    BOOL shouldMove = NO;
	
    float currentX = playerSprite.position.x;
    float currentY = playerSprite.position.y;
	
    if(acceleration.x > 0.25) {  // tilting the device upwards
        destX = currentX - (acceleration.y * kPlayerSpeed);
        destY = currentY + (acceleration.x * kPlayerSpeed);
        shouldMove = YES;
		
		[vehicle setMotorOn:YES];
		[vehicle reverse:NO];
		[vehicle steerLeft:NO];
		[vehicle steerRight:NO];
		NSLog(@">>>>>>>>>>>>> Go upwards");
		
    } else if (acceleration.x < -0.25) {  // tilting the device downwards
        destX = currentX - (acceleration.y * kPlayerSpeed);
        destY = currentY + (acceleration.x * kPlayerSpeed);
        shouldMove = YES;
		
		[vehicle reverse:YES];
		[vehicle setMotorOn:NO];
		[vehicle steerLeft:NO];
		[vehicle steerRight:NO];
		NSLog(@">>>>>>>>>>>>> Go downwards");
    } else if(acceleration.y < -0.25) {  // tilting the device to the right
        destX = currentX - (acceleration.y * kPlayerSpeed);
        destY = currentY + (acceleration.x * kPlayerSpeed);
        shouldMove = YES;
		
		[vehicle steerRight:YES];
		[vehicle steerLeft:NO];
		[vehicle setMotorOn:NO];
		[vehicle reverse:NO];
		NSLog(@">>>>>>>>>>>>> Go right");
    } else if (acceleration.y > 0.25) {  // tilting the device to the left
        destX = currentX - (acceleration.y * kPlayerSpeed);
        destY = currentY + (acceleration.x * kPlayerSpeed);
        shouldMove = YES;
		
		[vehicle steerLeft:YES];
		[vehicle steerRight:NO];
		[vehicle setMotorOn:NO];
		[vehicle reverse:NO];
		NSLog(@">>>>>>>>>>>>> Go left");
    } else {
        destX = currentX;
        destY = currentY;
    }
	
    if(shouldMove) {
        CGSize wins = [[CCDirector sharedDirector] winSize];
        // ensure we aren't moving out of bounds     
        if(destX < 0 || destX > wins.width - 0 || destY < 0 || destY > wins.height - 0) {
            // do nothing
        } 
    } 
	
	
}
-(void) reset {
	[race reset];
	
	[vehicle setMotorOn:NO];
	[vehicle reverse:NO];
	[vehicle steerLeft:NO];
	[vehicle steerRight:NO];
}

//2. Draw shape into this bitmap
-(void)DrawFilledPath {
	CGContextRef context = DrawingBitmap;
	
	CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);
	CGContextFillRect(context, CGRectMake( 0, 0, 1024, 1024));
	
	CGContextSetLineWidth(context, 2.0);
	
	CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
	
	//CGDrawing *drawing = [[CGDrawing alloc] init];
	
	int sectionsCount = [track->sections count];
	for (int i = 0; i < sectionsCount; i++) {
		Section *section = (Section*)[track->sections objectAtIndex:i];
		Rectangle *bounds = [section getBounds];
	
		if ([section type] == STRAIGHT) {
			StraightSection *straight = (StraightSection*)section;
			if ([straight isVertical]) {
				[drawing drawingLineWithContext:context StartPoint:ccp([bounds x], [bounds y]) EndPoint:ccp([bounds x], [bounds y] + [bounds height])];
				[drawing drawingLineWithContext:context StartPoint:ccp([bounds x] + [bounds width] - 1, [bounds y]) EndPoint:ccp([bounds x] + [bounds width] - 1, [bounds y] + [bounds height])];
				//ccDrawLine(ccp([bounds x], [bounds y]), ccp([bounds x], [bounds y] + [bounds height]));
				//ccDrawLine(ccp([bounds x] + [bounds width] - 1, [bounds y]), ccp([bounds x] + [bounds width] - 1, [bounds y] + [bounds height]));
			}
			else {
				[drawing drawingLineWithContext:context StartPoint:ccp([bounds x], [bounds y]) EndPoint:ccp([bounds x] + [bounds width], [bounds y])];
				[drawing drawingLineWithContext:context StartPoint:ccp([bounds x], [bounds y] + [bounds height] - 1) EndPoint:ccp([bounds x] + [bounds width], [bounds y] + [bounds height] - 1)];
//				ccDrawLine(ccp([bounds x], [bounds y]), ccp([bounds x] + [bounds width], [bounds y]));
//				ccDrawLine(ccp([bounds x], [bounds y] + [bounds height] - 1), ccp([bounds x] + [bounds width], [bounds y] + [bounds height] - 1));
			}
			
		}
		else {
			CornerSection *corner = (CornerSection*)section;
			
			if ([corner toTop] && [corner toLeft]) {
//				[drawing drawingLineWithContext:context StartPoint:ccp([corner cornerX], [corner cornerY]) EndPoint:ccp(480,320)];
				[drawing drawingArcWithContext:context 
											X1:ccp([corner cornerX], [corner cornerY] + [bounds height] - 1) 
											X2:ccp([corner cornerX] + [bounds width], [corner cornerY] + [bounds height])  
											X3:ccp([corner cornerX] + [bounds width] - 1, [corner cornerY]) 
											Radius:[bounds height]];
			}
			if ([corner toTop] && ![corner toLeft]) {
				//[drawing drawingLineWithContext:context StartPoint:ccp([corner cornerX], [corner cornerY]) EndPoint:ccp(480,320)];
				[drawing drawingArcWithContext:context 
											X1:ccp([corner cornerX], [corner cornerY] + [bounds height] - 1) 
											X2:ccp([corner cornerX] - [bounds width], [corner cornerY] + [bounds height])  
											X3:ccp([corner cornerX] - [bounds width], [corner cornerY]) 
										Radius:[bounds height]];
				
			}
			
			if (![corner toTop] && [corner toLeft]) {
				//[drawing drawingLineWithContext:context StartPoint:ccp([corner cornerX], [corner cornerY]) EndPoint:ccp(480,320)];
				[drawing drawingArcWithContext:context 
											X1:ccp([corner cornerX] + [bounds width] - 1, [corner cornerY]) 
											X2:ccp([corner cornerX] + [bounds width], [corner cornerY] - [bounds height])
											X3:ccp([corner cornerX], [corner cornerY] - [bounds height])   
										Radius:[bounds height]];
				
			}
			
			if (![corner toTop] && ![corner toLeft]) {
				//[drawing drawingLineWithContext:context StartPoint:ccp([corner cornerX], [corner cornerY]) EndPoint:ccp(480,320)];
				[drawing drawingArcWithContext:context 
											X1:ccp([corner cornerX], [corner cornerY] - [bounds height]) 
											X2:ccp([corner cornerX] - [bounds width], [corner cornerY] - [bounds height])
											X3:ccp([corner cornerX] - [bounds width], [corner cornerY])   
										Radius:[bounds height]];
				
			}
			
		}
		if ( i == 0 ) {
			Section* prev = [section getPreviousSection];
			Rectangle* prevBounds = [prev getBounds];
			[drawing drawingRectWithContext:context X:[prevBounds x] - [prevBounds width] Y:[prevBounds y] Width:[prevBounds width] Height:[prevBounds height]];
			//g.drawRect( prevBounds.x-1, prevBounds.y-1, prevBounds.width+2, prevBounds.height+2 );
		}
	}
	vehicles = [race getVehicles];
	for (int i =0; i < 1; i++) {
		Vehicle* vehicle = (Vehicle*)[vehicles objectAtIndex:i];
		State* state = [vehicle currentState];
		float angle = state->angle;
		for (int j = 0; j < 4; j++) {
			float testx = [[state->xpoints objectAtIndex:j] floatValue];
			float testy = [[state->ypoints objectAtIndex:j] floatValue];
			printf("xpoint %d : %f\n", j, testx);
			printf("ypoint %d : %f\n", j, testy);
		}
		
		[drawing drawingPolyWithContext:context xVertices:state->xpoints yVertices:state->ypoints];
	
		float steering_angle = vehicle->steering_angle;
		
		double dx = sin( angle + steering_angle );
		double dy = cos( angle + steering_angle );
		
		int len = 4;
		[drawing drawingLineWithContext:context StartPoint:ccp((int)(state->x + vehicle->wx1), (int)(state->y + vehicle->wy1))
							   EndPoint:ccp((int)(state->x + vehicle->wx1 - dx*len),(int)(state->y + vehicle->wy1 - dy*len))];
		[drawing drawingLineWithContext:context StartPoint:ccp((int)(state->x + vehicle->wx2), (int)(state->y + vehicle->wy2))
							   EndPoint:ccp((int)(state->x + vehicle->wx2 - dx*len), (int)(state->y + vehicle->wy2 - dy*len))];
	}
	
	CGContextStrokePath(context);
	
	[self SwapTexture];
} 
//3. Created a Texture2D from the bitmap
//4. Set a sprite's texture to this new texture.
-(void)SwapTexture {
	if( DrawingSprite != nil && DrawingSprite.parent == self )
	{
		[[DrawingSprite texture] dealloc];
		[self removeChild:DrawingSprite cleanup:YES];
	}
	
	CGImageRef ref = CGBitmapContextCreateImage(DrawingBitmap);
	DrawingImage = [UIImage imageWithCGImage:ref];
	CGImageRelease(ref);
	//3. Created a Texture2D from the bitmap
	DrawingTexture = [[CCTexture2D alloc] initWithImage:DrawingImage];
	//4. Set a sprite's texture to this new texture.
	DrawingSprite = [[CCSprite spriteWithTexture:DrawingTexture] retain];
	[DrawingSprite setAnchorPoint:ccp(0,0)];
	DrawingSprite.position = ccp(0, 0);
	//[DrawingSprite setScale: 1/1.5];
	[self addChild: DrawingSprite z:15];
}
// Swap texture use for all
-(CCSprite*)SwapTextureWithContext:(CGContextRef)context {
	CGImageRef ref = CGBitmapContextCreateImage(context);
	UIImage* uiImage = [UIImage imageWithCGImage:ref];
	CGImageRelease(ref);
	//3. Created a Texture2D from the bitmap
	CCTexture2D* texture = [[CCTexture2D alloc] initWithImage:uiImage];
	//4. Set a sprite's texture to this new texture.
	CCSprite* sprite = [[CCSprite spriteWithTexture:texture] retain];
	return sprite;
}

- (void)ccTouchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
	NSLog(@">>>>>>>>>>>>>>>> TouchBegan");
	UITouch *touch = [touches anyObject];
	oldPoint = [touch locationInView:[touch view]];
	oldPoint = [[CCDirector sharedDirector] convertToGL:oldPoint];
	
	float x = oldPoint.y - (self.position.x + DrawingSprite.position.x - DrawingSprite.anchorPoint.x * DrawingSprite.contentSize.width);
	float y = oldPoint.x - (self.position.y + DrawingSprite.position.y - DrawingSprite.anchorPoint.y * DrawingSprite.contentSize.height);
	
	if (x >= 0 && x <= DrawingSprite.contentSize.width && y >= 0 && y <= DrawingSprite.contentSize.height) {
		inside = YES;
	}
}

- (void)ccTouchesMoved:(NSSet*)touches withEvent:(UIEvent*)event {
	if (!inside) return;
	
	NSLog(@">>>>>>>>>>>>>>>> ccTouchesMoved");
	UITouch *touch = [touches anyObject];
    CGPoint point = [touch locationInView:[touch view]];
	point = [[CCDirector sharedDirector] convertToGL:point];
	
	// TODO
	DrawingSprite.position = ccp(clamp(DrawingSprite.position.x + point.x - oldPoint.x, 480-DrawingSprite.contentSize.width-0, 0), clamp(DrawingSprite.position.y + point.y - oldPoint.y, 320-DrawingSprite.contentSize.height-0, 0));
	
	oldPoint = point;
}

- (void)ccTouchesEnded:(NSSet*)touches withEvent:(UIEvent*)event {
	NSLog(@">>>>>>>>>>>>>>>> ccTouchesEnded");
	if (!inside) return;
	
	inside = NO;
}

-(void)gameUpdate:(ccTime)dt {
	//NSLog(@">>>>>>>>>>>>>>> Update game.");
	float dt1 = 0.05f;
	[race integrate:dt1];
	[self DrawFilledPath];
}

@end
